home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / cgterm10.zip / PIBASYN2.MOD < prev    next >
Text File  |  1993-04-01  |  23KB  |  331 lines

  1. (*----------------------------------------------------------------------*)
  2. (*          Async_Send --- Send character over communications port      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Send( C : Char );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Async_Send                                           *)
  10. (*                                                                      *)
  11. (*     Purpose:    Sends character out over communications port         *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Async_Send( C : Char );                                       *)
  16. (*                                                                      *)
  17. (*           C --- Character to send                                    *)
  18. (*                                                                      *)
  19. (*     Calls:  None                                                     *)
  20. (*                                                                      *)
  21. (*----------------------------------------------------------------------*)
  22.  
  23. BEGIN   (* Async_Send *)
  24.  
  25. INLINE(
  26.   $8A/$46/<C                          {         MOV     AL,[BP+<C]                 ;Pick up character to send}
  27.   /$8B/$1E/>ASYNC_OBUFFER_HEAD        {         MOV     BX,[>Async_OBuffer_Head]   ;Get output queue head pointer}
  28.   /$C4/$3E/>ASYNC_OBUFFER_PTR         {         LES     DI,[>Async_OBuffer_Ptr]    ;Pick up output buffer address}
  29.   /$01/$DF                            {         ADD     DI,BX                      ;Position to current character}
  30.   /$26/$88/$05                        {     ES: MOV     [DI],AL                    ;Place character in output buffer}
  31.                                       {;}
  32.   /$89/$DA                            {         MOV     DX,BX                      ;Save previous head pointer}
  33.   /$43                                {         INC     BX                         ;Increment head pointer}
  34.   /$3B/$1E/>ASYNC_OBUFFER_SIZE        {         CMP     BX,[>Async_OBuffer_Size]   ;See if past end of buffer}
  35.   /$7E/$02                            {         JLE     Send1                      ;Skip if not}
  36.   /$31/$DB                            {         XOR     BX,BX                      ;Wrap to start of buffer}
  37.                                       {;}
  38.   /$3B/$1E/>ASYNC_OBUFFER_TAIL        {Send1:   CMP     BX,[>Async_OBuffer_Tail]   ;See if head collided with tail}
  39.   /$75/$1C                            {         JNE     Send4                      ;No -- buffer didn't fill up}
  40.                                       {;}
  41.   /$8B/$0E/>ASYNC_OUTPUT_DELAY        {         MOV     CX,[>Async_Output_Delay]   ;Run delay loop and see if buffer drains}
  42.                                       {;}
  43.   /$51                                {Send2:   PUSH  CX                           ;Save milleseconds to go}
  44.   /$8B/$0E/$12/$00                    {         MOV   CX,[$12]                     ;Get Turbo's delay loop value for 1 ms}
  45.                                       {;}
  46.   /$E2/$FE                            {Send3:   LOOP  Send3                        ;Tight loop for 1 ms delay}
  47.                                       {;}
  48.   /$3B/$1E/>ASYNC_BUFFER_TAIL         {         CMP   BX,[>Async_Buffer_Tail]      ;See if buffer drained yet}
  49.   /$75/$0B                            {         JNE   Send4                        ;Yes -- OK, stop delay loop.}
  50.                                       {;}
  51.   /$59                                {         POP   CX                           ;Otherwise, get millesecond count}
  52.   /$E2/$F0                            {         LOOP  Send2                        ;Decrement millesecond count and loop}
  53.                                       {;}
  54.   /$C6/$06/>ASYNC_OBUFFER_OVERFLOW/$01{         MOV     BYTE [>Async_OBuffer_Overflow],1 ;Indicate output buffer overflow}
  55.   /$E9/$14/$00                        {         JMP     Send5                      ;Skip updating head pointers}
  56.                                       {;}
  57.   /$89/$1E/>ASYNC_OBUFFER_HEAD        {Send4:   MOV     [>Async_OBuffer_Head],BX   ;Save updated head pointer}
  58.                                       {;}
  59.   /$A1/>ASYNC_OBUFFER_USED            {         MOV     AX,[>Async_OBuffer_Used]   ;Get buffer use count}
  60.   /$40                                {         INC     AX                         ;Increment buffer use count}
  61.   /$A3/>ASYNC_OBUFFER_USED            {         MOV     [>Async_OBuffer_Used],AX   ;Save new count}
  62.   /$3B/$06/>ASYNC_MAXOBUFFERUSED      {         CMP     AX,[>Async_MaxOBufferUsed] ;See if larger than ever before}
  63.   /$7E/$03                            {         JLE     Send5                      ;Skip if not}
  64.   /$A3/>ASYNC_MAXOBUFFERUSED          {         MOV     [>Async_MaxOBufferUsed],AX ;Save new maximum usage}
  65.                                       {;}
  66.   /$8B/$16/>ASYNC_UART_IER            {Send5:   MOV     DX,[>Async_Uart_IER]       ;Get interrupt enable register}
  67.   /$EC                                {         IN      AL,DX                      ;Check contents of IER}
  68.   /$A8/$02                            {         TEST    AL,2                       ;See if write interrupt enabled}
  69.   /$75/$03                            {         JNZ     Send6                      ;Skip if so}
  70.   /$0C/$02                            {         OR      AL,2                       ;Else enable write interrupts ...}
  71.   /$EE                                {         OUT     DX,AL                      ;... by rewriting IER contents}
  72.                                       {;}
  73.                                       {Send6:}
  74. );
  75.  
  76. END    (* Async_Send *);
  77.  
  78. (*----------------------------------------------------------------------*)
  79. (*          Async_Receive --- Return character from buffer              *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. FUNCTION Async_Receive( VAR C : Char ) : BOOLEAN;
  83.  
  84. (*----------------------------------------------------------------------*)
  85. (*                                                                      *)
  86. (*     Function:   Async_Receive                                        *)
  87. (*                                                                      *)
  88. (*     Purpose:    Retrieve character (if any) from buffer              *)
  89. (*                                                                      *)
  90. (*     Calling Sequence:                                                *)
  91. (*                                                                      *)
  92. (*        Flag := Async_Receive( VAR C: Char ) : BOOLEAN;               *)
  93. (*                                                                      *)
  94. (*           C --- character (if any) retrieved from buffer;            *)
  95. (*                 set to CHR(0) if no character available.             *)
  96. (*                                                                      *)
  97. (*           Flag returned TRUE if character retrieved from buffer,     *)
  98. (*           Flag returned FALSE if no character retrieved.             *)
  99. (*                                                                      *)
  100. (*     Calls:  None                                                     *)
  101. (*                                                                      *)
  102. (*----------------------------------------------------------------------*)
  103.  
  104. BEGIN   (* Async_Receive *)
  105.  
  106. INLINE(
  107.                                  {;}
  108.                                  {;  Check if any characters in input comm buffer}
  109.                                  {;}
  110.   $A1/>ASYNC_BUFFER_TAIL         {         MOV   AX,[>Async_Buffer_Tail]}
  111.   /$3B/$06/>ASYNC_BUFFER_HEAD    {         CMP   AX,[>Async_Buffer_Head]}
  112.   /$75/$0B                       {         JNE   Rec1}
  113.                                  {;}
  114.                                  {;  Buffer is empty -- return NUL character}
  115.                                  {;}
  116.   /$C4/$7E/<C                    {         LES   DI,[BP+<C]                   ;Get character address}
  117.   /$31/$C0                       {         XOR   AX,AX                        ;Clear out unused bits}
  118.   /$26/$88/$05                   {     ES: MOV   [DI],AL                      ;NUL character}
  119.   /$E9/$41/$00                   {         JMP   Return}
  120.                                  {;}
  121.                                  {;  Buffer not empty -- pick up next character.}
  122.                                  {;}
  123.   /$C4/$3E/>ASYNC_BUFFER_PTR     {Rec1:    LES   DI,[>Async_Buffer_Ptr]       ;Pick up buffer address}
  124.   /$01/$C7                       {         ADD   DI,AX                        ;Add character offset}
  125.   /$26/$8A/$1D                   {     ES: MOV   BL,[DI]                      ;Get character from buffer}
  126.   /$C4/$7E/<C                    {         LES   DI,[BP+<C]                   ;Get result address}
  127.   /$26/$88/$1D                   {     ES: MOV   [DI],BL                      ;Store character from buffer}
  128.   /$40                           {         INC   AX                           ;Increment tail pointer}
  129.   /$3B/$06/>ASYNC_BUFFER_SIZE    {         CMP   AX,[>Async_Buffer_Size]      ;Past end of buffer?}
  130.   /$7E/$02                       {         JLE   Rec2                         ;No -- skip wrapping}
  131.   /$31/$C0                       {         XOR   AX,AX                        ;Yes -- point to start of buffer}
  132.   /$A3/>ASYNC_BUFFER_TAIL        {Rec2:    MOV   [>Async_Buffer_Tail],AX      ;Update tail pointer}
  133.   /$FF/$0E/>ASYNC_BUFFER_USED    {         DEC   Word [>Async_Buffer_Used]    ;Update buffer use count}
  134.                                  {;}
  135.                                  {; If XOFF previously sent because buffer was too full, and}
  136.                                  {; now buffer is reasonably empty, send XON to get things rolling again.}
  137.                                  {;}
  138.   /$F6/$06/>ASYNC_XOFF_SENT/$01  {         TEST  BYTE [<Async_XOff_Sent],1    ;Check if Xoff sent}
  139.   /$74/$18                       {         JZ    Rec3                         ;No -- skip.}
  140.                                  {;}
  141.   /$A1/>ASYNC_BUFFER_USED        {         MOV   AX,[>Async_Buffer_Used]      ;Pick up amount of buffer used}
  142.   /$3B/$06/>ASYNC_BUFFER_LOW     {         CMP   AX,[>Async_Buffer_Low]       ;Check if low enough}
  143.   /$7F/$0F                       {         JG    Rec3                         ;Still too full, skip}
  144.                                  {;}
  145.   /$B8/>XON                      {         MOV   AX,>XON                      ;Else push XON onto stack}
  146.   /$50                           {         PUSH  AX}
  147.   /$8D/$1E/>ASYNC_SEND           {         LEA   BX,[>Async_Send]             ;Call output routine}
  148.                                  {;}
  149.                                  {;-----WARNING---- Following statement must be fixed by hand in .OBJ file!}
  150.                                  {;---------------- Generated code should read:}
  151.                                  {;                 $FF/ $D3/}
  152.                                  {;}
  153.   /$FF/$D3                       {         CALL  [BX]                         ;THIS MUST BE FIXED BY HAND!!!!!}
  154.                                  {;}
  155.   /$C6/$06/>ASYNC_XOFF_SENT/$00  {         MOV   BYTE [>Async_XOff_Sent],0    ;Clear Xoff flag}
  156.                                  {;}
  157.                                  {;  Indicate character found}
  158.                                  {;}
  159.   /$B8/$01/$00                   {Rec3:    MOV    AX,1}
  160.                                  {;}
  161.   /$80/$26/>ASYNC_LINE_STATUS/$FD{Return:  AND    Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  162.   /$09/$C0                       {         OR     AX,AX                       ;Set zero flag to indicate return status}
  163.   /$89/$EC                       {         MOV    SP,BP}
  164.   /$5D                           {         POP    BP}
  165.   /$C2/$05/$00                   {         RET    5}
  166. );
  167.  
  168. END   (* Async_Receive *);
  169.  
  170. (*----------------------------------------------------------------------*)
  171. (*   Async_Receive_With_TimeOut --- Return char. from buffer with delay *)
  172. (*----------------------------------------------------------------------*)
  173.  
  174. PROCEDURE Async_Receive_With_Timeout( Secs : INTEGER; VAR C : INTEGER );
  175.  
  176. (*----------------------------------------------------------------------*)
  177. (*                                                                      *)
  178. (*     Procedure:  Async_Receive_With_Timeout                           *)
  179. (*                                                                      *)
  180. (*     Purpose:    Retrieve character as integer from buffer,           *)
  181. (*                 or return TimeOut if specified delay period          *)
  182. (*                 expires.                                             *)
  183. (*                                                                      *)
  184. (*     Calling Sequence:                                                *)
  185. (*                                                                      *)
  186. (*        Async_Receive_With_Timeout( Secs: INTEGER; VAR C: INTEGER );  *)
  187. (*                                                                      *)
  188. (*           Secs ---  Timeout period in seconds                        *)
  189. (*                     NOTE:  Cannot be longer than 32 seconds!         *)
  190. (*           C     --- ORD(character) (if any) retrieved from buffer;   *)
  191. (*                     set to TimeOut if no character found before      *)
  192. (*                     delay period expires.                            *)
  193. (*                                                                      *)
  194. (*     Calls:  Async_Receive                                            *)
  195. (*             TimeOfDay                                                *)
  196. (*                                                                      *)
  197. (*     WATCH OUT!  THIS ROUTINE RETURNS AN INTEGER, NOT A CHARACTER!!!  *)
  198. (*                                                                      *)
  199. (*----------------------------------------------------------------------*)
  200.  
  201. BEGIN (* Async_Receive_With_Timeout *)
  202.  
  203. INLINE(
  204.                                  {;}
  205.                                  {;  Check if a character in input comm buffer}
  206.                                  {;}
  207.   $A1/>ASYNC_BUFFER_TAIL         {         MOV   AX,[>Async_Buffer_Tail]}
  208.   /$3B/$06/>ASYNC_BUFFER_HEAD    {         CMP   AX,[>Async_Buffer_Head]}
  209.   /$75/$29                       {         JNE   Rec1}
  210.                                  {;}
  211.                                  {;  Buffer empty -- begin wait loop.}
  212.                                  {;}
  213.   /$8B/$46/<SECS                 {         MOV   AX,[BP+<Secs]                 ;Get seconds to wait}
  214.   /$B9/$0A/$00                   {         MOV   CX,10                         ;Shift count = 2 ** 10 = 1024}
  215.   /$D3/$E0                       {         SHL   AX,CL                         ;Seconds * 1024 = milleseconds}
  216.   /$89/$C1                       {         MOV   CX,AX                         ;Move to looping register}
  217.                                  {;}
  218.                                  {;  Delay for 1 ms.}
  219.                                  {;}
  220.   /$51                           {Delay:   PUSH  CX                            ;Save milleseconds to go}
  221.   /$8B/$0E/$12/$00               {         MOV   CX,[$12]                      ;Get Turbo's delay loop value for 1 ms}
  222.   /$E2/$FE                       {Delay1:  LOOP  Delay1                        ;Tight loop for 1 ms delay}
  223.                                  {;}
  224.                                  {;  Check if any character yet.}
  225.                                  {;}
  226.   /$A1/>ASYNC_BUFFER_TAIL        {         MOV   AX,[>Async_Buffer_Tail]}
  227.   /$3B/$06/>ASYNC_BUFFER_HEAD    {         CMP   AX,[>Async_Buffer_Head]}
  228.   /$75/$0F                       {         JNE   Rec1}
  229.                                  {;}
  230.                                  {;  Buffer still empty -- decrement elapsed time}
  231.                                  {;}
  232.   /$59                           {         POP   CX                            ;Get millesecond count}
  233.   /$E2/$ED                       {         LOOP  Delay                         ;Decrement millesecond count and loop}
  234.                                  {;}
  235.                                  {;  Dropped through -- no character arrived in specified interval.}
  236.                                  {;  Return TimeOut as result.}
  237.                                  {;}
  238.   /$BB/>TIMEOUT                  {         MOV   BX,>TimeOut                   ;Pick up timeout value}
  239.   /$C4/$7E/<C                    {         LES   DI,[BP+<C]                    ;Get result character address}
  240.   /$26/$89/$1D                   {    ES:  MOV   [DI],BX                       ;Store timeout value}
  241.   /$E9/$40/$00                   {         JMP   Return                        ;Return to caller}
  242.                                  {;}
  243.                                  {;  Buffer not empty -- pick up next character.}
  244.                                  {;}
  245.   /$C4/$3E/>ASYNC_BUFFER_PTR     {Rec1:    LES   DI,[>Async_Buffer_Ptr]        ;Pick up buffer address}
  246.   /$01/$C7                       {         ADD   DI,AX                         ;Add character offset}
  247.   /$26/$8A/$1D                   {     ES: MOV   BL,[DI]                       ;Get character from buffer}
  248.                                  {;}
  249.   /$30/$FF                       {         XOR   BH,BH                         ;Clear high-order bits}
  250.   /$C4/$7E/<C                    {         LES   DI,[BP+<C]                    ;Get result address}
  251.   /$26/$89/$1D                   {     ES: MOV   [DI],BX                       ;Store character from buffer}
  252.                                  {;}
  253.   /$40                           {         INC   AX                            ;Increment tail pointer}
  254.   /$3B/$06/>ASYNC_BUFFER_SIZE    {         CMP   AX,[>Async_Buffer_Size]       ;Past end of buffer?}
  255.   /$7E/$02                       {         JLE   Rec2                          ;No -- skip wrapping}
  256.   /$31/$C0                       {         XOR   AX,AX                         ;Yes -- point to start of buffer}
  257.   /$A3/>ASYNC_BUFFER_TAIL        {Rec2:    MOV   [>Async_Buffer_Tail],AX       ;Update tail pointer}
  258.   /$FF/$0E/>ASYNC_BUFFER_USED    {         DEC   Word [>Async_Buffer_Used]     ;Update buffer usage count}
  259.                                  {;}
  260.                                  {; If XOFF previously sent because buffer was too full, and}
  261.                                  {; now buffer is reasonably empty, send XON to get things rolling again.}
  262.                                  {;}
  263.   /$F6/$06/>ASYNC_XOFF_SENT/$01  {         TEST  BYTE [<Async_XOff_Sent],1    ;Check if Xoff sent}
  264.   /$74/$18                       {         JZ    Return                       ;No -- skip.}
  265.                                  {;}
  266.   /$A1/>ASYNC_BUFFER_USED        {         MOV   AX,[>Async_Buffer_Used]      ;Pick up amount of buffer used}
  267.   /$3B/$06/>ASYNC_BUFFER_LOW     {         CMP   AX,[>Async_Buffer_Low]       ;Check if low enough}
  268.   /$7F/$0F                       {         JG    Return                       ;Still too full, skip}
  269.                                  {;}
  270.   /$B8/>XON                      {         MOV   AX,>XON                      ;Push XON onto stack}
  271.   /$50                           {         PUSH  AX}
  272.   /$8D/$1E/>ASYNC_SEND           {         LEA   BX,[>Async_Send]             ;Call output routine}
  273.                                  {;}
  274.                                  {;-----WARNING---- Following statement must be fixed by hand in .OBJ file!}
  275.                                  {;---------------- Generated code should read:}
  276.                                  {;                 $FF/ $D3/}
  277.                                  {;}
  278.   /$FF/$D3                       {         CALL  [BX]                         ;THIS MUST BE FIXED BY HAND!!!!!}
  279.                                  {;}
  280.   /$C6/$06/>ASYNC_XOFF_SENT/$00  {         MOV   BYTE [>Async_XOff_Sent],0    ;Clear Xoff flag}
  281.                                  {;}
  282.   /$80/$26/>ASYNC_LINE_STATUS/$FD{Return:  AND   Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  283. );
  284.  
  285. END   (* Async_Receive_With_Timeout *);
  286.  
  287. (*----------------------------------------------------------------------*)
  288. (*        Async_Stuff --- Stuff character into receive buffer           *)
  289. (*----------------------------------------------------------------------*)
  290.  
  291. PROCEDURE Async_Stuff( Ch: CHAR );
  292.  
  293. (*----------------------------------------------------------------------*)
  294. (*                                                                      *)
  295. (*     Procedure:  Async_Stuff                                          *)
  296. (*                                                                      *)
  297. (*     Purpose:    Stuffs a character into receive buffer               *)
  298. (*                                                                      *)
  299. (*     Calling Sequence:                                                *)
  300. (*                                                                      *)
  301. (*        Async_Stuff( Ch : Char );                                     *)
  302. (*                                                                      *)
  303. (*           Ch --- Character to stuff                                  *)
  304. (*                                                                      *)
  305. (*     Calls:  None                                                     *)
  306. (*                                                                      *)
  307. (*----------------------------------------------------------------------*)
  308.  
  309. VAR
  310.    New_Head : INTEGER;
  311.  
  312. BEGIN (* Async_Stuff *)
  313.  
  314.    Async_Buffer_Ptr^[Async_Buffer_Head] := Ch;
  315.    New_Head                             := Async_Buffer_Head + 1;
  316.  
  317.    IF ( New_Head > Async_Buffer_Size ) THEN
  318.       New_Head := 0;
  319.  
  320.    IF ( New_Head = Async_Buffer_Tail ) THEN
  321.       Async_Buffer_Overflow := TRUE
  322.    ELSE
  323.       BEGIN
  324.          Async_Buffer_Head := New_Head;
  325.          Async_Buffer_Used := Async_Buffer_Used + 1;
  326.          IF ( Async_Buffer_Used > Async_MaxBufferUsed ) THEN
  327.             Async_MaxBufferUsed := Async_Buffer_Used
  328.       END;
  329.  
  330. END   (* Async_Stuff *);
  331.